﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AnimEditor.Define;
using AnimEditor.Picture;
using AnimEditor.Properties;
using System.Collections;
using System.Drawing.Imaging;
using System.IO;
using AnimEditor.Anim;
using AnimEditor.Tile;

namespace AnimEditor
{

public partial class MainForm : Form
{
    public MainForm()
    {
      InitializeComponent();
    }


    #region Message
    private void MainMenuItemFileOpen_Click(object sender, EventArgs e)
    {
      OpenFileDialog ofd = new OpenFileDialog();
      ofd.Filter = "CCA Files (*.cca)|*.cca";
      ofd.FilterIndex = 1;
      DialogResult ret = ofd.ShowDialog(this);
      if (ret != DialogResult.OK)
        return;

      string filename=ofd.FileName;
      int extnameindex = filename.LastIndexOf('.');
      if(extnameindex==-1)
        return ;
      string extname = filename.Substring(extnameindex+1);

      if (extname.ToLower().Equals("cca"))
      {
        Clear();
        string imagename = ofd.FileName.Substring(0, ofd.FileName.LastIndexOf('\\') + 1) + "Image\\" + ofd.SafeFileName.Substring(0, ofd.SafeFileName.LastIndexOf('.') + 1) + "png";
        if (!ReadPng(imagename))
          return ;
        if (!ReadCCA(ofd.FileName))
          return ;

        Lst_Tiles.DataBindings.Clear();
        Lst_Tiles.DataSource = null;
        Lst_Tiles.DataSource = TileMgr.Instance.Tile_Sprites;
        Lst_Tiles.DisplayMember = "Name";

        foreach(AnimData data in AnimMgr.Instance.AnimDataLst)
        {
          AnimTreeNode treenode = new AnimTreeNode(data);
          for (int i = 0 ; i < data.AnimFrame.Count ; ++i  )
          {
            AnimFrameData framedata = data.AnimFrame[i];
            AnimFrameTreeNode frametreenode = new AnimFrameTreeNode(framedata);
            frametreenode.Text = string.Format("Frame{0}", i); 
            treenode.Nodes.Add(frametreenode);
          }
          AnimShowTree.Nodes.Add(treenode);
        }
      }
    }

    private void MainMenuItemFileSave_Click(object sender, EventArgs e)
    {
      if (PicMgr.Instance.BitMap == null)
        return;
      SaveFileDialog sfd = new SaveFileDialog();
      sfd.Filter = "CCA File(*.cca)|*.cca";
      DialogResult ret = sfd.ShowDialog(this);
      if (ret != DialogResult.OK)
        return;

      string directoryname = sfd.FileName;
      int directorynameindex = directoryname.IndexOf('.');
      if (directorynameindex != -1)
        directoryname = directoryname.Substring(0, directorynameindex);
      int filenameindex = directoryname.LastIndexOf('\\');
      if (filenameindex == -1)
        return ;
      string filename = directoryname.Substring(filenameindex + 1);


      Directory.CreateDirectory(directoryname);
      Directory.CreateDirectory(string.Format("{0}\\Image", directoryname));
      string pngfilename = string.Format("{0}\\Image\\{1}.png", directoryname, filename);
      SavePNG(pngfilename);
      string ccafilename = string.Format("{0}\\{1}.cca", directoryname, filename);
      SaveCCA(ccafilename);
    }

    private void MainPicShowPanel_Scroll(object sender, ScrollEventArgs e)
    {
      if (e.Type == ScrollEventType.ThumbTrack)
      {
        MainPicShowPanel.Invalidate();
      }
    }

    private void AddAnimBtn_Click(object sender, EventArgs e)
    {
      int maxi=0;
      IEnumerator ienum = AnimShowTree.Nodes.GetEnumerator();
      while(ienum.MoveNext())
      {
        TreeNode Node = (TreeNode)ienum.Current;
        if(Node.Text.StartsWith("NewAnim"))
        {
          string Numstr = Node.Text.Substring(7);
          int i;
          if (Int32.TryParse(Numstr,out i))
          {
            if (i > maxi)
              maxi = i;
          }
        }
      }
      
      AnimData data = AnimMgr.Instance.CreateAnimData();
      AnimTreeNode treenode = new AnimTreeNode(data);
      data.Name = string.Format("NewAnim{0}", maxi + 1);
      AnimShowTree.Nodes.Add(treenode);
      AnimShowTree.Select();
      AnimShowTree.SelectedNode = treenode;
    }

    private void SortBtn_Click(object sender, EventArgs e)
    {
      if (PicMgr.Instance.BitMap == null || TileMgr.Instance.Tile_Sprites.Count == 0)
        return;

      FTextureLayout Layout = new FTextureLayout(2, 2, 1024, 1024, true);
      int RectX;
      int RectY;


      List<SortRect> NewRectLst = new List<SortRect>();
      List<TileData> TileLst = TileMgr.Instance.Tile_Sprites;

      for (int i = 0; i < TileLst.Count; ++i)
      {
        TileData data = TileLst[i];
        if (Layout.AddElement(out RectX, out RectY, data.Rect.Width, data.Rect.Height))
        {
          NewRectLst.Add(new SortRect(data, new AnimPoint(RectX, RectY)));
        }
        else
          return;
      }
      Bitmap newbitmap = new Bitmap(Layout.SizeX, Layout.SizeY);
      BitmapData newbitmapdata = newbitmap.LockBits(new Rectangle(0, 0, newbitmap.Width, newbitmap.Height), ImageLockMode.ReadWrite, newbitmap.PixelFormat);
      Color color;
      unsafe
      {
        int* rgbValues = (int*)newbitmapdata.Scan0.ToPointer();

        for (int index = 0; index < NewRectLst.Count; ++index)
        {
          SortRect rect = NewRectLst[index];
          for (int i = 0; i < rect.mTileData.Rect.Height; ++i)
          {
            for (int j = 0; j < rect.mTileData.Rect.Width; ++j)
            {

              if (j + rect.mTileData.Rect.X < PicMgr.Instance.BitMap.Width && i + rect.mTileData.Rect.Y < PicMgr.Instance.BitMap.Height)
                color = PicMgr.Instance.BitMap.GetPixel(j + rect.mTileData.Rect.X, i + rect.mTileData.Rect.Y);
              else
                color = Color.FromArgb(0);
              int tmp = color.A << 24 | color.R << 16 | color.G << 8 | color.B;
              rgbValues[(i + rect.mPoint.Y) * newbitmapdata.Width + (j + rect.mPoint.X)] = tmp;
            }
          }
          Rectangle tmprect = new Rectangle();
          tmprect.X = rect.mPoint.X;
          tmprect.Y = rect.mPoint.Y;
          tmprect.Width = rect.mTileData.Rect.Width;
          tmprect.Height = rect.mTileData.Rect.Height;
          rect.mTileData.Rect = tmprect;
        }
      }
      newbitmap.UnlockBits(newbitmapdata);
      MainPicShowPanel.ShowBitMap = newbitmap;
      MainPicShowPanel.Invalidate();
    }

    private void LstView_Pictures_DragDrop(object sender, DragEventArgs e)
    {
      if (e.Data.GetDataPresent(DataFormats.FileDrop))
      {
        List<string> Files = new List<string>((string[])e.Data.GetData(DataFormats.FileDrop));
        foreach (string File in Files)
        {
          if (System.IO.File.Exists(File))
          {
            ReadPng(File);
          }
        }
      }
    }

    private void LstView_Pictures_DragOver(object sender, DragEventArgs e)
    {
      if (e.Data.GetDataPresent(DataFormats.FileDrop))
      {
        e.Effect = DragDropEffects.Move;
      }
    }

    private void MainPicShowPanel_MouseClick(object sender, MouseEventArgs e)
    {
		List<TileData> Tiles = TileMgr.Instance.Tile_Sprites;
		int MounseX = e.X;
		int MounseY = e.Y;
		int Index = 0;
		foreach (TileData Tile in Tiles)
		{
			if (MounseX + MainPicShowPanel.HorizontalScroll.Value > Tile.Rect.X && MounseX + MainPicShowPanel.HorizontalScroll.Value < (Tile.Rect.X + Tile.Rect.Size.Width)
				&& MounseY + MainPicShowPanel.VerticalScroll.Value > Tile.Rect.Y && MounseY + MainPicShowPanel.VerticalScroll.Value < (Tile.Rect.Y + Tile.Rect.Size.Height))
			{
				SelectTile(Index);
				break;
			}
			Index++;
		}
    }

    private void MainForm_Load(object sender, EventArgs e)
    {


      //  Lst_Tiles.bind
    }

    private void Lst_Tiles_SelectedIndexChanged(object sender, EventArgs e)
    {
      string text = this.Lst_Tiles.Text;
      int index = 0;
      foreach (TileData tile in TileMgr.Instance.Tile_Sprites)
      {
        if (text.Equals(tile.Name))
        {
			SelectTile(index);
			return;
        }
        index++;
      }
    }

    private void PopMenu_MainPic_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
    {
      if (e.ClickedItem.Tag.ToString().Equals("MakeTile"))
      {
        MakeTileForm batchForm = new MakeTileForm(this);
        batchForm.StartPosition = FormStartPosition.CenterScreen;
        batchForm.Show();
        return;
      }
    }

    private void AnimTreePropertyGrid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
    {
      Lst_Tiles.DataBindings.Clear();
      Lst_Tiles.DataSource = null;
      Lst_Tiles.DataSource = TileMgr.Instance.Tile_Sprites;
      Lst_Tiles.DisplayMember = "Name";
    }

    private void AnimShowTree_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
    {
      TreeNode NowNode = (TreeNode)e.Node;

      if (NowNode.Parent == null)
      {
        AnimTreeNode AnimNode = (AnimTreeNode)NowNode;
        AnimTreePropertyGrid.SelectedObject = AnimNode.Data;
      }
      else
      {
        AnimFrameTreeNode AnimFrameNode = (AnimFrameTreeNode)NowNode;
        AnimTreePropertyGrid.SelectedObject = AnimFrameNode.FrameData;
      }
      PicMgr.Instance.SelTreeNode = NowNode;
      MainPicShowPanel.Invalidate();
      return;
    }

    private void MainMenuItemPicOpen_Click(object sender, EventArgs e)
    {
      OpenFileDialog ofd = new OpenFileDialog();
      ofd.Filter = "PNG Files (*.png)|*.png";
      ofd.FilterIndex = 1;
      DialogResult ret = ofd.ShowDialog(this);
      if (ret != DialogResult.OK)
        return;

      string filename = ofd.FileName;
      int extnameindex = filename.LastIndexOf('.');
      if (extnameindex == -1)
        return;
      string extname = filename.Substring(extnameindex + 1);

      if (extname.ToLower().Equals("png"))
      {
        ReadPng(ofd.FileName);
      }
    }

    private void MainMenuItemPigSave_Click(object sender, EventArgs e)
    {
      if (PicMgr.Instance.BitMap == null)
        return;
      SaveFileDialog ofd = new SaveFileDialog();
      ofd.Filter = "PNG File (*.png)|*.png";
      DialogResult ret = ofd.ShowDialog(this);
      if (ret != DialogResult.OK)
        return;
      SavePNG(ofd.FileName);
    }

    private void MainPicShowPanel_MouseMove(object sender, MouseEventArgs e)
    {
      Val_MousePos.Text = string.Format("{0},{1}", e.X + MainPicShowPanel.HorizontalScroll.Value, e.Y + MainPicShowPanel.VerticalScroll.Value);
      Val_MousePos.Invalidate();
    }

    private void Btn_Play_MouseClick(object sender, MouseEventArgs e)
    {
    }

    private void Btn_Pause_MouseClick(object sender, MouseEventArgs e)
    {
    }

    private void MainMenuItemPicSave_Click(object sender, EventArgs e)
    {
      SaveFileDialog sfd = new SaveFileDialog();
      sfd.Filter = "PNG File(*.png)|*.png";
      DialogResult ret = sfd.ShowDialog(this);
      if (ret != DialogResult.OK)
        return;
      SavePNG(sfd.FileName);
    }
    #endregion

	#region Logic
	public void SelectTile(int index)
	{
		Lst_Tiles.SelectedIndex = index;
		ShapePicPanel.ShowTileIndex = index;
		ShapePicPanel.Invalidate(false);
		MainPicShowPanel.SelectedTile = index;
		MainPicShowPanel.Invalidate(false);
	}

	public void DeleteTile(TileData removetile)
	{
		TileMgr.Instance.Tile_Sprites.Remove(removetile);

		SelectTile(-1);
		Lst_Tiles.DataSource = null;
		Lst_Tiles.DataSource = TileMgr.Instance.Tile_Sprites;
		Lst_Tiles.DisplayMember = "Name";
		ShapePicPanel.Invalidate();
	}

    public bool SavePNG(string pngname)
    {      
      PicMgr.Instance.BitMap.Save(pngname, ImageFormat.Png);
      return true;
    }

    public bool SaveCCA(string ccaname)
    {
      FileStream ccafile = new FileStream(ccaname, FileMode.Create);

      BinaryWriter writer = new BinaryWriter(ccafile);
      writer.Write("cca");
      TileMgr.Instance.Write(writer);
      AnimMgr.Instance.Write(writer);
      writer.Flush();
      ccafile.Close();

      return true;
    }

	public bool ReadPng(string pngname)
	{
		try
		{
			Bitmap filebitmap = new Bitmap(pngname);
			Bitmap oldbitmap = MainPicShowPanel.ShowBitMap;
			int oldwidth = 0;
			int oldheight = 0;
			if (oldbitmap != null)
			{
				oldwidth = oldbitmap.Width;
				oldheight = oldbitmap.Height;
			}
			int width = filebitmap.Size.Width > oldwidth ? filebitmap.Size.Width : oldwidth;
			int height = filebitmap.Size.Height + oldheight;
			PicMgr.Instance.NewBitmapSize.Width = filebitmap.Size.Width;
			PicMgr.Instance.NewBitmapSize.Height = filebitmap.Size.Height;

			Bitmap newbitmap = new Bitmap(width, height);
			BitmapData newbitmapdata = newbitmap.LockBits(new Rectangle(0, 0, newbitmap.Width, newbitmap.Height), ImageLockMode.ReadWrite, newbitmap.PixelFormat);
			int bytes = Math.Abs(newbitmapdata.Stride) * newbitmapdata.Height;
			int bytesperpixel = newbitmapdata.Stride / newbitmap.Width;
			if (bytesperpixel != 4 || newbitmapdata.Stride % newbitmap.Width != 0)
			{
				throw new Exception("错误的图形格式");
			}
			unsafe
			{
				int* rgbValues = (int*)newbitmapdata.Scan0.ToPointer();
				if (oldbitmap != null)
				{
					for (int i = 0; i < oldbitmap.Height; ++i)
					{
						for (int j = 0; j < oldbitmap.Width; ++j)
						{
							Color color = oldbitmap.GetPixel(j, i);
							int tmp = color.A << 24 | color.R << 16 | color.G << 8 | color.B;
							rgbValues[i * newbitmapdata.Width + j] = tmp;
						}
					}
				}

				for (int i = 0; i < filebitmap.Height; ++i)
				{
					for (int j = 0; j < filebitmap.Width; ++j)
					{
						Color color = filebitmap.GetPixel(j, i);
						int tmp = color.A << 24 | color.R << 16 | color.G << 8 | color.B;
						rgbValues[(i + oldheight) * newbitmapdata.Width + j] = tmp;
					}
				}
			}
			newbitmap.UnlockBits(newbitmapdata);

			MainPicShowPanel.ShowBitMap = newbitmap;
			MainPicShowPanel.Invalidate();
		}
		catch (System.Exception ex)
		{
			string str = string.Format("Load Picture Error\n%s", ex.ToString());
			MessageBox.Show(str, "Error");
			return false;
		}
		return true;
	}

	public bool ReadCCA(string ccaname)
	{
		string str;
		try
		{
			FileStream ccafile = new FileStream(ccaname, FileMode.Open);
			BinaryReader reader = new BinaryReader(ccafile);
			str = reader.ReadString();
			if (!str.Equals("cca"))
				throw new System.Exception("错误的文件格式");
			TileMgr.Instance.Read(reader);
			AnimMgr.Instance.Read(reader);
			reader.Close();
		}
		catch (System.Exception ex)
		{
			Clear();
			System.Console.WriteLine(ex.ToString());
			return false;
		}

		return true;
	}

	public void Clear()
	{
		for (int i = 0; i < AnimShowTree.Nodes.Count; ++i)
		{
			AnimTreeNode node = (AnimTreeNode)AnimShowTree.Nodes[i];
			node.Clear();
		}
		AnimShowTree.Nodes.Clear();

		Lst_Tiles.DataBindings.Clear();
		Lst_Tiles.DataSource = null;
		PicMgr.Instance.Clear();
		TileMgr.Instance.Clear();
		AnimMgr.Instance.Clear();
		AnimTreePropertyGrid.SelectedObject = null;
	}
		#endregion

		private void PopMenu_TileLst_DeleteTile_Click(object sender, ToolStripItemClickedEventArgs e)
		{
			if(e.ClickedItem.Tag.ToString().Equals("DeleteTile"))
			{
				if (Lst_Tiles.SelectedIndex!=-1)
				{
					TileData removetile = Lst_Tiles.SelectedItem as TileData;
					TileMgr.Instance.Tile_Sprites.Remove(removetile);

					SelectTile(-1);
					Lst_Tiles.DataSource = null;
					Lst_Tiles.DataSource = TileMgr.Instance.Tile_Sprites;
					Lst_Tiles.DisplayMember = "Name";
					ShapePicPanel.Invalidate();
				}
			
			}
		}

}

class SortRect
{
	public TileData mTileData = null;
	public AnimPoint mPoint = null;

	public SortRect(TileData tile, AnimPoint point)
	{
		mTileData = tile;
		mPoint = point;
	}
}
}
